package ru.ifmo.tanya.service.impl;

import org.jdom.Element;
import ru.ifmo.tanya.core.calls.Call;
import ru.ifmo.tanya.core.calls.CallManager;
import ru.ifmo.tanya.core.huntgroups.HuntGroup;
import ru.ifmo.tanya.core.users.User;
import ru.ifmo.tanya.core.users.UserManager;
import ru.ifmo.tanya.db.HuntGroupManager;
import ru.ifmo.tanya.service.XmlService;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;


public class ShowSuperStatsService extends XmlService {

    private final CallManager callManager = new CallManager();
    private final UserManager userManager = new UserManager();
    private final HuntGroupManager huntGroupManager = new HuntGroupManager();

    @Override
    public void invoke(User user, HttpServletRequest request, Element response) {

        List<Call> allCalls = callManager.getAllCalls();

        int unitsCount = Integer.parseInt(request.getParameter("units-count"));
        TimeUnit timeUnit = TimeUnit.valueOf(request.getParameter("time-unit").toUpperCase());
        allCalls = filterCallsByTime(allCalls, timeUnit, unitsCount);

        String userIdString = request.getParameter("filter-user-id");
        if (userIdString != null) {
            allCalls = filterCallsByAnswerer(allCalls, userManager.getUserById(Integer.parseInt(userIdString)));
        }

        String huntGroupIdString = request.getParameter("hunt-group-id");
        if (huntGroupIdString != null) {
            allCalls = filterCallsByHuntGroup(allCalls, huntGroupManager.getHuntGroupById(Integer.parseInt(huntGroupIdString)));
        }
        response.addContent(serializeCalls(allCalls));
    }

    public Element serializeCalls(List<Call> calls) {
        Element result = new Element("calls");
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
        for (Call call : calls) {
            Element callElement = new Element("call");
            callElement.setAttribute("caller", call.getCaller());
            callElement.setAttribute("hunt-group", call.getHuntGroup().getName());

            User answerer = call.getAnswerer();
            if (answerer != null) {
                callElement.setAttribute("answerer", answerer.getName());
            } else {
                callElement.setAttribute("answerer", "");
            }

            callElement.setAttribute("started", dateFormat.format(call.getCreationTime()));

            Date answerTime = call.getAnswerTime();
            if (answerTime != null) {
                callElement.setAttribute("answered", dateFormat.format(answerTime));
                callElement.setAttribute("hold-time", formatTime(answerTime.getTime() - call.getCreationTime().getTime()));
            } else {
                callElement.setAttribute("answered", "");
                callElement.setAttribute("hold-time", "");
            }

            Date completionTime = call.getCompletionTime();
            if (completionTime != null) {
                callElement.setAttribute("completed", dateFormat.format(completionTime));
            } else {
                callElement.setAttribute("completed", "");
            }

            if (completionTime != null && answerTime != null) {
                callElement.setAttribute("duration", formatTime(completionTime.getTime() - call.getAnswerTime().getTime()));
            } else if (answerTime != null) {
                callElement.setAttribute("duration", "");
            } else {
                callElement.setAttribute("duration", "00:00:00");
            }

            String whoFinished = call.getWhoFinished();
            if (whoFinished != null) {
                switch (whoFinished) {
                    case "caller":
                        callElement.setAttribute("who-finished", "Завершен клиентом");
                        break;
                    case "agent":
                        callElement.setAttribute("who-finished", "Завершен агентом");
                        break;
                }
            } else {
                if (completionTime == null) {
                    if (answerTime == null) {
                        callElement.setAttribute("who-finished", "В очереди");
                    } else {
                        callElement.setAttribute("who-finished", "В процессе");
                    }
                } else {
                    callElement.setAttribute("who-finished", "Завершен клиентом");
                }
            }
            result.addContent(callElement);
        }
        return result;
    }

    private List<Call> filterCallsByTime(List<Call> calls, TimeUnit unit, int unitsCount) {
        Date cuttingDate = new Date(unit.toMillis(unitsCount));
        List<Call> result = new ArrayList<>();
        for (final Call call : calls) {
            if (call.getCreationTime().after(cuttingDate)) {
                result.add(call);
            }
        }
        return result;
    }

    private List<Call> filterCallsByAnswerer(List<Call> calls, User answerer) {
        List<Call> result = new ArrayList<>();
        for (final Call call : calls) {
            if (answerer.equals(call.getAnswerer())) {
                result.add(call);
            }
        }
        return result;
    }

    private List<Call> filterCallsByHuntGroup(List<Call> calls, HuntGroup huntGroup) {
        List<Call> result = new ArrayList<>();
        for (final Call call : calls) {
            if (huntGroup.equals(call.getHuntGroup())) {
                result.add(call);
            }
        }
        return result;
    }

    private String formatTime(long millis) {
        return String.format("%02d:%02d:%02d",
                TimeUnit.MILLISECONDS.toHours(millis),
                TimeUnit.MILLISECONDS.toMinutes(millis) -
                        TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
                TimeUnit.MILLISECONDS.toSeconds(millis) -
                        TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
    }

    @Override
    public String getXslFilePath() {
        return "/xsl/super-stat.xsl";
    }
}
